<?php
// +----------------------------------------------------------------------
// | ScrollPHP
// +----------------------------------------------------------------------
// | @copyright Copyright (c) 2014 PhpStorm All rights reserved.
// +----------------------------------------------------------------------
// | @license Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | @author LIZHEN
// +----------------------------------------------------------------------
// | @version 0.0.1 (2014-09-04)
// +----------------------------------------------------------------------
// | @info $Id: ScrollPHP.class.php 2766 14-3-28 下午4:26 LIZHEN $
// +----------------------------------------------------------------------
// | @package

if(version_compare(PHP_VERSION,'5.0.0','<')) exit('您的PHP版本太低，不能使用本框架');

defined('APP_PATH')         || define( 'APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']));
defined('FRAMEWORK_PATH')   || define( 'FRAMEWORK_PATH', dirname(__FILE__));
defined('MODULES_PATH')     || define( 'MODULES_PATH',   APP_PATH . '/Modules');
defined('CONFIGS_PATH')     || define( 'CONFIGS_PATH',   APP_PATH . '/Configs');
defined('CACHE_PATH')       || define( 'CACHE_PATH',     APP_PATH . '/Cache');
defined('VENDOR_PATH')      || define( 'VENDOR_PATH',    FRAMEWORK_PATH.'/Vendor'); // 第三方类库目录

include_once FRAMEWORK_PATH . '/Functions/Global.func.php';
tp_include( FRAMEWORK_PATH . '/Base.class.php' );
tp_include( FRAMEWORK_PATH . '/Logger.class.php' );

define('IS_CGI',substr(PHP_SAPI, 0,3)=='cgi' ? 1 : 0 );
define('IS_WIN',strstr(PHP_OS, 'WIN') ? 1 : 0 );
define('IS_CLI',PHP_SAPI=='cli'? 1   :   0);

if(!IS_CLI) {
    // 当前文件名
    if(!defined('_PHP_FILE_')) {
        if(IS_CGI) {
            //CGI/FASTCGI模式下
            $_temp  = explode('.php',$_SERVER['PHP_SELF']);
            define('_PHP_FILE_', rtrim(str_replace($_SERVER['HTTP_HOST'],'',$_temp[0].'.php'),'/'));
        }else {
            define('_PHP_FILE_', rtrim($_SERVER['SCRIPT_NAME'],'/'));
        }
    }
    if(!defined('__ROOT__')) {
        // 网站URL根目录
        if( strtoupper(APP_NAME) == strtoupper(basename(dirname(_PHP_FILE_))) ) {
            $_root = dirname(dirname(_PHP_FILE_));
        }else {
            $_root = dirname(_PHP_FILE_);
        }
        define('__ROOT__',   (($_root=='/' || $_root=='\\')?'':$_root));
    }
}

$app = ScrollPHP::getInstance();
$app->run();


class ScrollPHP
{
    private static $_instance = null;

    private function __construct()
    {
        tp_include(FRAMEWORK_PATH . '/Config/ConfigFactory.class.php');
        C(ConfigFactory::factory()); //写入配置信息
        session_start();
        date_default_timezone_set(C('timeZone'));
        if (true === C('debug')) {
            //Logger::log('debug mode');
            ini_set('display_errors', 'On');
            error_reporting(C('errorReporting'));
        } else {
            error_reporting(0);
            ini_set('display_errors', 'Off');
        }

        if(!is_dir(APP_PATH) || !is_dir(MODULES_PATH)) {
            // 创建应用目录结构
            require FRAMEWORK_PATH . '/Functions/Build.func.php';
        }

        header('Content-type: text/html; charset='.C('charset'));
    }

    private function __clone()
    {
    }

    /**
     + --------------------------------------------------
     * 预处理传入的数据
     + --------------------------------------------------
     * @access private
     * @param void
     * @return void
     + --------------------------------------------------
     */
    private function _preDealData() {

        // Magic quotes are anything but magic - lose them!
        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() == 1) {
            function stripslashes_gpc(&$value,$key){
                //Logger::log($key .':'. $value);
                $value = stripslashes($value);
            }

            if (count($_GET))
                array_walk_recursive ($_GET, 'stripslashes_gpc');
            if (count($_POST))
                array_walk_recursive ($_POST, 'stripslashes_gpc');
            if (count($_COOKIE))
                array_walk_recursive ($_COOKIE, 'stripslashes_gpc');
            if (count($_REQUEST))
                array_walk_recursive ($_REQUEST, 'stripslashes_gpc');
        }

    }

    /**
     + --------------------------------------------------
     * 对某个数据进行addslashes处理
     + --------------------------------------------------
     * @access private
     * @param mixed $data
     * @return mixed
     + --------------------------------------------------
     */
    private function _addSlashes($data) {
        if(is_array($data)) {
            //此处暂时只支持两层,本来可以递归调用，但是出于效率的考虑，舍弃了此方法
            foreach($data as $key => $val) {
                $data[$key] = addslashes($val);
            }
        } else {
            $data = addslashes($data);
        }
        return $data;
    }

    public static function getInstance()
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new ScrollPHP();
        }
        return self::$_instance;
    }

    public function run()
    {
        // 注册AUTOLOAD方法
        spl_autoload_register(array('ScrollPHP', 'autoload'));
        set_error_handler(array('ScrollPHP', 'appErrorHandler'));
        set_exception_handler(array('ScrollPHP','appException'));
        $this->_preDealData();
        Route::run();
    }

    public static function autoload($className)
    {
        $name = str_replace('_','/',$className);
        $name.= '.class.php';

        //用户类
        $name = implode('/',explode('_',$name));
        if('Model' === (substr($className,-5))){
            if(require_array(array(
                MODULES_PATH.'/Models/'.$name
            ),true)) {
                return false;
            }
        } elseif ('Controller' === (substr($className,-10))) {
            if(require_array(array(
                    MODULES_PATH.'/Controllers/'.$name,
                    FRAMEWORK_PATH.'/'.$name
                    ),true)) {
                return false;
            }
        } elseif ('Helper' === (substr($className,-6))) {
            //在Helpers下面搜索
            if(require_array(array(
                MODULES_PATH.'/Helpers/'.$name
            ),true)) {
                return false;
            }
        } elseif ('Exception' === (substr($className,-9))) {
            //在Helpers下面搜索
            if(require_array(array(
                FRAMEWORK_PATH.'/Exception/'.$name
            ),true)) {
                return false;
            }
        } elseif (is_file(MODULES_PATH.'/Models/'.$name)){
            //在Model下面搜索
            if(require_array(array(
                MODULES_PATH.'/Models/'.$name),true)) {
                return false;
            }
        } elseif(is_file(MODULES_PATH.'/Filters/'.$name)) {
            //在Filter下面搜索
            if(require_array(array(
                MODULES_PATH.'/Filters/'.$name
            ),true)) {
                return false;
            }
        } elseif(is_file(FRAMEWORK_PATH.'/'.$name)
            || is_file(FRAMEWORK_PATH.'/Driver/'.$name)
            || is_file(FRAMEWORK_PATH.'/Helper/'.$name)
            || is_file(FRAMEWORK_PATH.'/View/'.$name)
            ){
            if(require_array(array(
                FRAMEWORK_PATH.'/'.$name,
                FRAMEWORK_PATH.'/Driver/'.$name,
                FRAMEWORK_PATH.'/Helper/'.$name,
                FRAMEWORK_PATH.'/View/'.$name,
            ),true)) {
                return false;
            }
        } else {
            //可扩展
            return false;
        }

        if(class_exists($className)) {
            return true;
        } else {
            echo '<br/><font color = "red">[ERROR]类',$className,'不存在或未找到</font>';
            return false;
        }

    }
	
	/**
	 * 加载数据模型
	 * @param string $classname 类名
	 */
	public static function load_model($classname) {
		return self::_load_class($classname,'Models');
	}
	
	/**
	 * 加载类文件函数
	 * @param string $classname 类名
	 * @param string $path 扩展地址
	 * @param intger $initialize 是否初始化
	 */
	private static function _load_class($classname, $path = '', $initialize = 1) {
		static $classes = array();
		if (empty($path)) return false;
		$key = md5($path.$classname);
		if (isset($classes[$key])) {
			if (!empty($classes[$key])) {
				return $classes[$key];
			} else {
				return true;
			}
		}
		
		$name = '';
		if (file_exists(FRAMEWORK_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php')) {
			include FRAMEWORK_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php';
			Logger::log("加载：" . FRAMEWORK_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php');
			$name = $classname;
		} else if(file_exists(MODULES_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php')) {
			include MODULES_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php';
			Logger::log("加载：" . MODULES_PATH.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$classname.'.class.php');
			$name = $classname;
		}
		if(empty($name)){
			return false;
		}
		
		if ($initialize) {
			$classes[$key] = new $name;
		} else {
			$classes[$key] = true;
		}
		return $classes[$key];
		
	}
	
    // error handler function
    /**
     * 通过触发错误并以用户自定义的程序来进行内部异常的处理
     * @param $errno 包含了错误的级别，是一个 integer。
     * @param $errstr 包含了错误的信息，是一个 string。
     * @param $errfile 包含了发生错误的文件名，是一个 string。
     * @param $errline 包含了错误发生的行号，是一个 integer。
     * @return bool
     */
    public static function appErrorHandler($errno, $errstr, $errfile, $errline){
        if (!(error_reporting() & $errno)) {
            // This error code is not included in error_reporting
            return;
        }

        switch ($errno) {
            case E_USER_ERROR:
                echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
                echo "  Fatal error on line $errline in file $errfile";
                echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
                echo "Aborting...<br />\n";
                exit(1);
                break;

            case E_USER_WARNING:
                echo "<b>My WARNING</b> [$errfile][line:$errline][$errno] $errstr<br />\n";
                break;

            case E_USER_NOTICE:
                echo "<b>My NOTICE</b> [$errfile][line:$errline][$errno] $errstr<br />\n";
                break;

            default:
                echo "Unknown error type: [$errfile][line:$errline][$errno] $errstr<br />\n";
                break;
        }

        return true;
    }

    /**
     *
     * @param BaseException $e
     */
    public static function appException(BaseException $e){
        //echo $e->getMessage();
        $e->printStack();
    }

}